package ext.tianma.part.finishedProduct.util;

import java.rmi.RemoteException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Vector;

import wt.csm.constraint.CSMSingleDefConstraint;
import wt.csm.navigation.CSMClassificationNavigationException;
import wt.csm.navigation.ClassificationNode;
import wt.csm.navigation.litenavigation.ClassificationNodeDefaultView;
import wt.csm.navigation.litenavigation.ClassificationNodeNodeView;
import wt.csm.navigation.service.ClassificationHelper;
import wt.csm.navigation.service.ClassificationObjectsFactory;
import wt.fc.ObjectIdentifier;
import wt.fc.PersistenceHelper;
import wt.fc.PersistenceServerHelper;
import wt.fc.QueryResult;
import wt.fc.ReferenceFactory;
import wt.fc.collections.WTHashSet;
import wt.fc.collections.WTSet;
import wt.iba.constraint.FloatContentRange;
import wt.iba.constraint.IntegerContentDiscreteSet;
import wt.iba.constraint.IntegerContentRange;
import wt.iba.constraint.SingleValued;
import wt.iba.constraint.StringContentDiscreteSet;
import wt.iba.constraint.ValueConstraint;
import wt.iba.constraint.ValueRequired;
import wt.iba.definition.ReferenceDefinition;
import wt.iba.definition.litedefinition.AttributeDefDefaultView;
import wt.iba.value.DefaultAttributeContainer;
import wt.iba.value.IBAHolder;
import wt.iba.value.ReferenceValue;
import wt.iba.value.litevalue.AbstractValueView;
import wt.iba.value.litevalue.ReferenceValueDefaultView;
import wt.iba.value.service.IBAValueHelper;
import wt.method.RemoteAccess;
import wt.part.WTPart;
import wt.pds.StatementSpec;
import wt.query.QueryException;
import wt.query.QuerySpec;
import wt.query.SearchCondition;
import wt.util.WTException;
import ext.tianma.part.finishedProduct.vo.ClassAttrRuleVo;

public class CSMUtil implements RemoteAccess{

	public static ClassAttrRuleVo getClassAttrInfo(ClassificationNode node,String attrName) throws CSMClassificationNavigationException, RemoteException, WTException{
		ClassificationNodeDefaultView cndv=ClassificationObjectsFactory.newClassificationNodeDefaultView(node);
		cndv=ClassificationHelper.service.refreshClassificationNodeDefaultView(cndv);
		DefaultAttributeContainer dac = (DefaultAttributeContainer)cndv.getAttributeContainer();
		AttributeDefDefaultView avv[] = dac.getAttributeDefinitions();
		
		ClassAttrRuleVo attrRuleVo = new ClassAttrRuleVo();
		for (int i=0; i<avv.length; i++) {
			String ibaName=avv[i].getName();
			if(ibaName.equals(attrName)){
				String ibaLabel=avv[i].getLocalizedDisplayString();
				attrRuleVo.setDisplayName(ibaLabel);
				attrRuleVo.setDataType(avv[i].getAttributeDefinitionClassName());
				getClassAttrRule(node,avv[i],attrRuleVo);
				break;
			}
		}
		return attrRuleVo;
	}
	
	public static void getClassAttrRule(ClassificationNode node,AttributeDefDefaultView avv,ClassAttrRuleVo attrRuleVo) throws WTException{
		QuerySpec select = new QuerySpec(CSMSingleDefConstraint.class);
		select.appendWhere(new SearchCondition(
				CSMSingleDefConstraint.class,
				"theAttributeDefReference.key.id",
				"=", avv.getObjectID().getId()), new int[] { 0 });
		select.appendAnd();
		select.appendWhere(new SearchCondition(
				CSMSingleDefConstraint.class,
				"theIBAHolderReference.key", "=",
				node.getPersistInfo().getObjectIdentifier()),
				new int[] { 0 });
		QueryResult qr = PersistenceHelper.manager.find((StatementSpec) select);
		while (qr.hasMoreElements()) {
			CSMSingleDefConstraint constraint = (CSMSingleDefConstraint) qr
					.nextElement();
			ValueConstraint valueConstraint = constraint.getValueConstraint();
			if (valueConstraint instanceof ValueRequired) {
				//要求值
				attrRuleVo.setRequired(true);
			}else if(valueConstraint instanceof SingleValued){
				//单值
				attrRuleVo.setSingleValued(true);
			}else if(valueConstraint instanceof StringContentDiscreteSet){
				//合法值字符串集
				StringContentDiscreteSet scds = (StringContentDiscreteSet) valueConstraint;
				Vector discreteSet = scds.getDiscreteSet();
				attrRuleVo.setLegalValueList(Collections.list(discreteSet.elements()));
			}else if(valueConstraint instanceof IntegerContentRange){
				//整数范围
				attrRuleVo.setIntRange((IntegerContentRange) valueConstraint);
			}else if(valueConstraint instanceof IntegerContentDiscreteSet){
				//一组整数
				IntegerContentDiscreteSet scds = (IntegerContentDiscreteSet) valueConstraint;
				Vector discreteSet = scds.getDiscreteSet();
				Integer[] intArray = new Integer[discreteSet.size()];
				for(int i = 0;i<discreteSet.size();i++){
					intArray[i] = Integer.parseInt(String.valueOf(discreteSet.elementAt(i)));
				}
				attrRuleVo.setIntArray(intArray);
			}else if(valueConstraint instanceof FloatContentRange){
				//实数范围
				attrRuleVo.setFloatRange((FloatContentRange) valueConstraint);
			}
		}
	}
	
    /**
     *  取得分类节点的属性定义
     * @param node
     * @return Map<内部名称,显示名称>
     */
    public static Map<String,String> getClassNodeAllIBAs(ClassificationNode node) {
    	Map<String,String> retMap = new HashMap<String,String>();
    	try {
    		ClassificationNodeDefaultView cndv=ClassificationObjectsFactory.newClassificationNodeDefaultView(node);
    		cndv=ClassificationHelper.service.refreshClassificationNodeDefaultView(cndv);
    		DefaultAttributeContainer dac = (DefaultAttributeContainer)cndv.getAttributeContainer();
			AttributeDefDefaultView avv[] = dac.getAttributeDefinitions();
			for (int i=0; i<avv.length; i++) {
				String ibaName=avv[i].getName();
				String ibaLabel=avv[i].getLocalizedDisplayString();
				retMap.put(ibaName, ibaLabel);
			}
        } catch (Exception e) {
    		e.printStackTrace();
    	}
    	return retMap;
    }
    
    public static ClassificationNode getClassificationNodeByDefaultNodeView(ClassificationNodeDefaultView nodeView)
			throws WTException {
		ClassificationNode node = null;
		if(nodeView == null){
			throw new WTException("分类节点不存在,请检查");
		}
		ObjectIdentifier objid = nodeView.getObjectID();
		ReferenceFactory rf = new ReferenceFactory();
		Object obj = rf.getReference(objid.toString()).getObject();
		if ((obj instanceof ClassificationNode)) {
			node = (ClassificationNode) obj;
		}
		return node;
	}
    
    public static ClassificationNodeDefaultView getcfnByFullName(String fullName){
		String nodeName = fullName.substring(fullName.lastIndexOf("/")+1);
		Vector vector = getClassificationNodeDefaultViewByName(nodeName);
		for(int i=0;i<vector.size();i++){
			ClassificationNodeDefaultView cndv = (ClassificationNodeDefaultView)vector.get(i);
			String full = getClassificationFullPath(cndv);
			if(full != null && fullName.trim().equals(full.trim())){
				return cndv;
			}
		}
		return null;
	}
	
	public static ClassificationNode getClassificationNodeByNodeView(ClassificationNodeNodeView nodeView)
			throws WTException {
		ClassificationNode node = null;
		ObjectIdentifier objid = nodeView.getObjectID();
		ReferenceFactory rf = new ReferenceFactory();
		Object obj = rf.getReference(objid.toString()).getObject();
		if ((obj instanceof ClassificationNode)) {
			node = (ClassificationNode) obj;
		}
		return node;
	}
	
	public static Vector getClassificationNodeDefaultViewByName(String sNodeName) {
		Vector vector = new Vector();
		ClassificationNodeDefaultView cndv = null;
		QueryResult queryresult = null;
		try {
			QuerySpec queryspec = new QuerySpec(ClassificationNode.class);

			queryspec.appendSearchCondition(new SearchCondition(ClassificationNode.class, "name",SearchCondition.EQUAL, sNodeName,
					false));
			queryresult = PersistenceHelper.manager.find(queryspec);
		} catch (QueryException queryexception) {
			queryexception.printStackTrace();
			System.out.println("Cannot find Reference Definition!");
			return null;
		} catch (WTException wte) {
			System.out.println("Cannot Find Query Result Set!");
			return null;
		}
		while (queryresult.hasMoreElements()) {
			ClassificationNode classNode = null;
			classNode = (ClassificationNode) queryresult.nextElement();

			if (classNode != null) {
				try {
					cndv = ClassificationObjectsFactory.newClassificationNodeDefaultView(classNode);
					vector.addElement(cndv);
				} catch (CSMClassificationNavigationException cne) {
					System.out.println("ERROR: Cannot convert Classification Node from Heavy to Lite!");
				}
				continue;
			}

		}
		return vector;
	}
	
	public static String getClassificationFullPath(ClassificationNodeDefaultView clsNodeDftView) {
		if (clsNodeDftView == null)
			return "";
		String clsPath = clsNodeDftView.getName();
		ClassificationNodeDefaultView tmpNodeView = null;
		try {
			tmpNodeView = ClassificationHelper.service.getParentNodeDefaultView(clsNodeDftView);
			for (; tmpNodeView != null; tmpNodeView = ClassificationHelper.service
					.getParentNodeDefaultView(tmpNodeView)) {
				clsPath = tmpNodeView.getName() + "/" + clsPath;
			}
		} catch (RemoteException rme2) {
			rme2.printStackTrace();
			System.out.println("Cannot find Classification Structure Parent Node");
		} catch (CSMClassificationNavigationException csmclassificationnavigationexception2) {
			csmclassificationnavigationexception2.printStackTrace();
			System.out.println("Cannot find Classification Structure Parent Node");
		} catch (WTException wte2) {
			wte2.printStackTrace();
			System.out.println("Cannot find Classification Structure Parent Node");
		}
		return clsPath;
	}
	
	
	public static ClassificationNode getClassNodeByPart(WTPart wtpart) throws WTException {
		IBAHolder ibaHolder = null;
		ClassificationNode clsNode = null;
		try {
			ibaHolder = IBAValueHelper.service.refreshAttributeContainerWithoutConstraints(wtpart);
			DefaultAttributeContainer theContainer = (DefaultAttributeContainer) ibaHolder.getAttributeContainer();
			if (theContainer != null) {
				AttributeDefDefaultView[] theAtts = theContainer.getAttributeDefinitions();

				for (int i = 0; i < theAtts.length; i++) {
					AbstractValueView[] theValues = theContainer.getAttributeValues(theAtts[i]);

					if (theValues != null) {
						Object[] temp = new Object[2];
						temp[0] = theAtts[i];
						temp[1] = theValues[0];

						if(temp[1] instanceof ReferenceValueDefaultView 
								&& theAtts[i].getName().equalsIgnoreCase("Part")){
							String sNodeId = ((ReferenceValueDefaultView) theValues[0]).getLiteIBAReferenceable()
									.getReferencedLiteObject().getObjectID().getStringValue();
							ObjectIdentifier nodeOID = ObjectIdentifier.newObjectIdentifier(sNodeId);

							clsNode = (ClassificationNode) PersistenceHelper.manager.refresh(nodeOID);
							break;
						}
					}
				}
			} else {
				System.out.println("container is null");
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
		return clsNode;
	   }
	}
	
	/**
	 * 删除部件的分类
	 * @param part
	 * @throws WTException
	 */
	public static void clearPartClassficationNode(WTPart part) throws WTException{
		WTSet refValueSet = new WTHashSet();
	    QuerySpec qs = new QuerySpec(ReferenceValue.class);
	    qs.appendWhere(new SearchCondition(ReferenceValue.class, ReferenceValue.IBAHOLDER_REFERENCE + ".key", "=",
	    		PersistenceHelper.getObjectIdentifier(part)), new int[] { 0 });
	    QueryResult qr = PersistenceHelper.manager.find(qs);
	    while (qr.hasMoreElements()) {
	     refValueSet.add(qr.nextElement());
	    }    
	    PersistenceServerHelper.manager.remove(refValueSet);
	    PersistenceServerHelper.manager.update(part);
	}
	
	/**
	  * 设置部件PartsLink分类
	  * @param part
	  * @param node
	  * @throws WTException
	  */
	public static void setPartClassficationNode(WTPart part,ClassificationNode node) throws WTException{
		try {
			QuerySpec select = new QuerySpec(ReferenceDefinition.class);
			select.appendWhere(new SearchCondition(ReferenceDefinition.class, 
					ReferenceDefinition.NAME,SearchCondition.EQUAL, "Part"));//"part"为WTPart定义的分类的内部名称
			QueryResult result = PersistenceHelper.manager.find(select);
			if (result.hasMoreElements()) {
				ReferenceDefinition rd = (ReferenceDefinition) result.nextElement();
				ReferenceValue rv = ReferenceValue.newReferenceValue(rd, part, node);
				PersistenceHelper.manager.save(rv);
			} else {
				throw new ExceptionInInitializerError("Can't found Classification Reference.");
			}
		} catch (WTException ex) {
			throw new ExceptionInInitializerError(ex);
		}
	}
}
